package org.aspectsense.middleware.monitor;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.logging.Logger;

import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleListener;

/**
 * Implements the OSGi bundle listener for listening to bundle changes.<p>
 * Whenever a new <code>BundleEvent</code> is generated it overrides the
 * bundleChanged method to catch and manage received bundle events.
 */
public class DefaultBundleListener implements BundleListener
{

	private static final Logger logger = Logger.getLogger(DefaultBundleListener.class.getCanonicalName());
	private BundleEvent bundleEvent;


	
	
	@Override
	    /**
	     * Overrides the OSGi <code>bundleChanged</code> method
	     * in order to catch bundle events
	     */
	    public void bundleChanged (BundleEvent event)
	    {
			this.bundleEvent = event;
	       /* logger.info("DefaultBundleListener::bundleChanged -> " +
	                event + " / "
	                + handleBundleEvents(event.getType()));*/
	        
	        
	    }
		/**
		 * Handles OSGi Bundles changes events.
		 * Specific actions are taken in case an OSGi
		 * Bundle is: installed, started, stopped, updated
		 * uninstalled, resolved, unresolved
		 * @param code
		 * @return the name of the detected event
		 */
	    private String handleBundleEvents(final int code)
	    {
	        switch (code)
	        {
	            case BundleEvent.INSTALLED: {
	            	//handleInstalled();
	            	return "installed";
	            }
	            case BundleEvent.STARTED: {
	            	//printClassesInABundle();
	            	return "started";
	            }
	            case BundleEvent.STOPPED: return "stopped";
	            case BundleEvent.UPDATED: return "updated";
	            case BundleEvent.UNINSTALLED: return "uninstalled";
	            case BundleEvent.RESOLVED: return "resolved";
	            case BundleEvent.UNRESOLVED: return "unresolved";
	            case BundleEvent.STARTING: return "starting";
	            case BundleEvent.STOPPING: return "stopping";
	            case BundleEvent.LAZY_ACTIVATION: return "lazy_activation";
	            default: return "*unknown*";
	        }
	    }
	    private boolean handleInstalled ()
	    {
	    	//printClassesInABundle(this.bundleEvent.getBundle().getClass().getPackage().getName());
	    	
			return false;
	    
	    }
	    /*private void printClassesInABundle (){
	    	
	    	assert(this.bundleEvent!=null);
	    	try {
	    		Enumeration<URL> classPaths = this.bundleEvent.getBundle().findEntries("/", "*.class", true);
	    		Class<?>[] classes = getClasses(classPaths);
				
	    		for (Class<?> c:classes){
	    			 System.out.println (c.getSimpleName());
				 }
	    		
			} catch (ClassNotFoundException e) {
				logger.info("DefaultBundleListener::printClassesInABundle->ClassNotFoundException");
				e.printStackTrace();
				
			} catch (IOException e) {
				logger.info("DefaultBundleListener::printClassesInABundle->IOException");
				e.printStackTrace();
			}
	    }*/
	    
	    /**
	     * Scans all classes accessible from the context class loader
	     * which belong to the given package and subpackages.
	     *
	     * @param packageName The base package
	     * @return The classes
	     * @throws ClassNotFoundException
	     * @throws IOException
	     */

		private  Class<?>[] getClasses (Enumeration<URL> classPaths)throws ClassNotFoundException, IOException {
	        
	    	//ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
	       //ClassLoader classLoader = this.bundleEvent.getBundle().getClass().getClassLoader();
	    	//assert classLoader != null;
	        //String path = packageName.replace('.', '/');
	     
			//ClassLoader classLoader =this.bundleEvent.getSource().getClass().getClassLoader();
			/*Annotation[] an = this.bundleEvent.getSource().getClass().getAnnotations();
			System.out.println("Length"+an.length);
			for(Annotation a:an){
				System.out.println("HERE");
				System.out.println(a.annotationType());
				
			}*/
			Enumeration<URL> resources = classPaths;
	        ArrayList <Class<?>> classes = new ArrayList<Class<?>>();
	        String[] tok= new String[2];
	        String className;
	       
	        while (resources.hasMoreElements()) {
	        	
	        	URL classPath = resources.nextElement();
	        	tok = classPath.toString().split("/bin/");
	        	className = tok[1].substring(0, tok[1].length()-6);
	        	//System.out.println("getClasses::ClassName="+className);
	        	//Class<?> c = Class.forName(className, false, classLoader);
	        	//Class<?> c = this.bundleEvent.getBundle().loadClass(className);
	        	//classes.add(c);
	       
	        }

	        return (Class[]) classes.toArray(new Class[classes.size()]);
	    }

	    
}
	    